package com.ease.common.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.ease.common.vo.XmlObjectNotationBean;

/**
 * 
 * @author nathanleewei
 * 
 */
public class XmlObjectNotationUtil extends Detect {

	private static final transient Log log = LogFactory.getLog(XmlObjectNotationUtil.class);

	public static final String DEFAULT_ROOT_NAME = "xml";

	public void setValue(String xmlValue, Object object) throws Exception {
		setValue(xmlValue, object, null);
	}

	public void setValue(String xmlValue, Object object, XmlObjectNotationCallback callback) throws Exception {
		if (null != object) {
			if (object instanceof XmlObjectNotationBean) {
				XmlObjectNotationBean bean = (XmlObjectNotationBean) object;
				bean.setXml(xmlValue);
			}
			// if (!isValid(rootName)) {
			// rootName = DEFAULT_ROOT_NAME;
			// }
			Map<String, Object> parameters = getParameters(xmlValue);
			if (null != callback) {
				parameters = callback.convert(parameters);
			}
			setValue(parameters, object);
		}
	}

	public void setValue(Map<String, Object> parameters, Object object) {
		if (null != object) {
			if (null != parameters) {
				Map<String, Object> hash = new HashMap<String, Object>();
				hash.put("root", object);

				for (Iterator<Map.Entry<String, Object>> iterator = parameters.entrySet().iterator(); iterator.hasNext();) {
					Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iterator.next();
					String name = entry.getKey().toString();
					//
					if (entry.getValue() instanceof List) {
						List<?> valueList = (List<?>) entry.getValue();
						String[] valuesArray = new String[valueList.size()];
						valueList.toArray(valuesArray);
						hash.put(name, valuesArray);
					} else {
						hash.put(name, entry.getValue());
					}
				}
				hash = null;
			}
		}
	}

	public Map<String, Object> getParameters(String xmlValue) throws Exception {
		Assertion.notNull(xmlValue, "xmlValue not found");
		Document doc = null;
		Map<String, Object> parameters = new HashMap<String, Object>();

		try {
			doc = DocumentHelper.parseText(xmlValue.trim());
		} catch (DocumentException e) {
			if (log.isDebugEnabled()) {
				log.debug("DocumentHelper.parseText(xmlValue) failed! xmlValue=" + xmlValue);
				throw e;
			}
		}
		if (null != doc && null != doc.getRootElement()) {
			Element root = doc.getRootElement();
			String rootName = "";
			root.getName();
			if (null != root.elements()) {
				Element childElement = null;
				for (int i = 0; i < root.elements().size(); i++) {
					childElement = (Element) root.elements().get(i);
					appendParameters(rootName, parameters, childElement);
				}
			}
		}

		return parameters;
	}

	@SuppressWarnings("unchecked")
	private void appendParameters(String prefix, Map<String, Object> parameters, Element element) {
		if (null != element.elements() && element.elements().size() > 0) {
			Element childElement = null;
			for (int i = 0; i < element.elements().size(); i++) {
				childElement = (Element) element.elements().get(i);
				appendParameters(key(prefix, element), parameters, childElement);
			}
		} else {
			if (null != element.getText()) {

				Object value = parameters.get(key(prefix, element));
				if (null == value) {
					parameters.put(key(prefix, element), element.getText());
				} else {
					if (value instanceof List) {
						((List<String>) value).add(element.getText());
					} else {
						List<String> values = new ArrayList<String>();
						values.add((String) value);
						values.add(element.getText());
						parameters.put(key(prefix, element), values);
					}
				}
			}
		}
	}

	private String key(String prefix, Element element) {
		return (notEmpty(prefix) ? (prefix + ".") : "") + element.getName();
	}

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		StringBuffer xml = new StringBuffer();
		xml.append("<xml>");
		xml.append("	<areaCode>-1</areaCode>");
		xml.append("	<subAreaCode>subAreaCode</subAreaCode>");
		xml.append("	<operationType>installAddr</operationType>");
		xml.append("	<prodId>12</prodId>");
		xml.append("	<prodId>13</prodId>");
		xml.append("	<prodId></prodId>");
		xml.append("	<prodSpecId>");
		xml.append("		<prodId>12</prodId>");
		xml.append("		<operationType>installAddr</operationType>");
		xml.append("	</prodSpecId>");
		xml.append("</xml>");

		Map<String, Object> xmlParameters = null;
		try {
			xmlParameters = new XmlObjectNotationUtil().getParameters(xml.toString());
		} catch (Exception e) {

			e.printStackTrace();
		}

		System.out.println(xmlParameters);
		if (null != xmlParameters) {
			for (Map.Entry<String, Object> entry : xmlParameters.entrySet()) {
				String name = entry.getKey().toString();
				if (entry.getValue() instanceof List) {
					List<String> valueList = (List<String>) entry.getValue();
					for (int i = 0; i < valueList.size(); i++) {
						System.out.println(name + " = \"" + valueList.get(i) + "\"");
					}
				} else {
					System.out.println(name + " = \"" + entry.getValue() + "\"");
				}

			}
		}
	}
}